﻿/*
 * Folks Ajax Framework 0.2.0
 *
 * Copyright (c) 2008 Eduardo Dias (codeplex.com/folks)
 * Licensed under the MS-PL license.
 *
 */
function FolksManager()
{
	if(this instanceof FolksManager)
		FolksManager.prototype.init();
	else
		return new FolksManager();
}

FolksManager.prototype = 
{
	init : function()
	{
		this.__evtt = "__EVENTTARGET";
		this.__evta = "__EVENTARGUMENT";
		this.__evtv = "__EVENTVALIDATION";
		this.__vs = "__VIEWSTATE";
		this.__lf = "__LASTFOCUS";
		this.__fc = "__FOLKSCONTAINER";
		this.__captureAll = false;
		this.__onBeginRequest = null;
		this.__onEndRequest = null;
		$(document).ready
		(
			function()
			{ 
				FolksManager.getInstance().ensureEvents();
				FolksManager.getInstance().initialize();
			}
		);
	},
	initialize : function ()
	{
		$('form').find(':submit').each(function(){ FolksManager.getInstance().configureButton($(this)); });
		$('*[rel=folks:progress]').hide();
	},
	getInstance : function()
	{
		return FolksManager.getInstance();
	},
	captureAll : function(capture)
	{
		this.__captureAll = capture;
	},
	ensureEvents : function()
	{
		window.__originalDoPostBack = window.__doPostBack;
		window.__doPostBack = function(t,v){ FolksManager.getInstance().doPostBack(t,v); };
	},
	ensureEventTarget : function(eventTarget)
	{
		var target = $('*[name=' + eventTarget + ']');
		if(target.length == 0)
			target = $('#' + eventTarget);
		if(target.length == 0)
			target = $('#' + eventTarget.split('$').join('_'));
		if(target.length == 0)
			target = $('*[name=' + eventTarget.substring(0, eventTarget.lastIndexOf('$')) + ']');
		return target;
	},
	ensureEventFields : function()
	{
		var field = '<input type="hidden" />';
		var evtt = $('#' + this.__evtt);
		var evta = $('#' + this.__evta);
		
		if(evtt.length == 0)
			$(field).attr('id', this.__evtt).attr('name', this.__evtt).appendTo('form');
			
		if(evta.length == 0)
			$(field).attr('id', this.__evta).attr('name', this.__evta).appendTo('form');
	},
	fromContainer : function(target)
	{
		return target.parents('*[scope=folks]').length > 0;
	},
	getContainer : function(target)
	{
		return target.parents('*[scope=folks]');
	},
	beginRequest : function(target)
	{
		this.onBeginRequest();
		if(this.fromContainer(target))
		{
			var container = this.getContainer(target);
			if(container.attr('rel') != '')
			{
				var progress = $('#' + container.attr('rel'));
				if(progress.length > 0 && progress.is('*[rel=folks:progress]'))
					progress.show();
			}
			else
				$('*[rel=folks:progress]').show();
		}
		else
			$('*[rel=folks:progress]').show();
	},
	endRequest : function()
	{
		this.onEndRequest();
		$('*[rel=folks:progress]').hide();
	},
	onBeginRequest : function()
	{
		if(arguments.length > 0 && typeof(arguments[0]) == 'function')
			this.__onBeginRequest = arguments[0];
		else if(this.__onBeginRequest != null)
			this.__onBeginRequest();
	},
	onEndRequest : function()
	{
		if(arguments.length > 0){
			if(typeof(arguments[0]) == 'function')
				this.__onEndRequest = arguments[0];
		}else if(this.__onEndRequest != null)
			this.__onEndRequest();
	},
	isFolksPostBack : function(target)
	{
		return (this.__captureAll || target.is('*[rel=folks]') || 
				target.parents('*[rel=folks]').length > 0 ||
				target.parents('*[scope=folks]').length > 0);
	},
	doPostBack : function(eventTarget, eventArgument)
	{
		var folks = this;
		var status = false;
		var target = folks.ensureEventTarget(eventTarget);
		try
		{
			if(folks.isFolksPostBack(target))
			{
				folks.ensureEventFields();
				$('#' + this.__evtt).val(eventTarget);
				$('#' + this.__evta).val(eventArgument);
				
				var data = folks.parseData(target, eventTarget, eventArgument);

				$.ajax
				(
					{
						url : $('form').attr('action'),
						type : "POST",
						dataType : "html",
						data : data,
						beforeSend : function(request){ folks.beginRequest(target); },
						complete : function(request,status){ folks.endRequest(); },
						success : function(response){ folks.renderResponse(response, target); },
						error : folks.renderError
					}
				);
				status = true;
			}
			else if(window.__originalDoPostBack != null)
			{
				window.__originalDoPostBack(eventTarget, eventArgument);
				status = true;
			}
		}
		catch(ex)
		{
			if(ex != null && ex.message != null)
				alert(ex.message);
		}
		if(target.is(':submit'))
			return status;
	},
	parseData : function(target, eventTarget, eventArgument)
	{
		var data = {};
		var dataContent = "";
		if(this.fromContainer(target))
		{
			var container = this.getContainer(target);
			container.attr('name', this.__fc);
			dataContent += this.parseDataItem(container, container.attr('id'), true);
		}
		dataContent += this.parseCommonForm();
		eval("data = {" + dataContent + "}");
		return data;
		
	},
	parseCommonForm : function()
	{
		var dataStr = '';
		var form = this.$($('form').attr('id'));
		for(var i=0;(form != null && form.elements != null) && i<form.elements.length;i++)
		{
			var element = $(form.elements[i]);
			if(!element.is(':submit'))
				dataStr += this.parseDataItem(element, null, (i<form.elements.length-1)); 
		}
		return dataStr;
	},
	parseDataItem : function(element, value, comma, allowNull)
	{
		var item = '';
		if(!element.is(':radio,:checkbox') || (element.is(':radio,:checkbox') && element.is(':checked')))
		{
			value = value || element.val();
			if(value != null || (allowNull != 'undefined' && allowNull == true)){
				item += element.attr('name') + ' : ';
				item += '\'' + this.escape(value) + '\'';
				item += (comma == null || comma == true) ? ',' : '';
			}
		}
		return item;	
	},
	renderResponse : function(response, target)
	{ 
		if(this.fromContainer(target))
		{
			this.renderContainer(response);
		}
		else
		{
			$('form').html($('<div>').append(response).find('form').html());
			
		}
		this.initialize();
	},
	renderContainer : function(response)
	{
		var data = response.split('|@|');
		if(data.length == 5)
		{
			$('#' + this.__vs).val(data[1]);
			$('#' + this.__evtv).val(data[2]);
			
			var focus = $('#' + this.__lf);
			if(focus.length > 0)
				focus.val(data[3]);
			
			$('#' + data[0]).html(data[4]);
		}
	},
	renderError : function(request, error, exception)
	{
		if(request.status == '500')
		{
			var response = request.responseText;
			response = response.replace(/[\w\s\S]*<title>/, '');
			response = response.replace(/<\/title>[\w\s\S]*/, '');
			alert(response);
		}
	},
	
	configureButton : function(button)
	{
		if(button)
		{
			var folks = this;
			button.unbind('click').bind('click', function(){ return !folks.doPostBack(button.attr('name'), ''); });
		}
	},
	escape : function(text)
	{
		return text.split('\\').join('\\\\'); 
	},
	$ : function(id)
	{
		return document.getElementById(id);
	}
}

FolksManager.getInstance = function() 
{ 
	if(window.__folks)
		return window.__folks; 
	else
		return new FolksManager();
}

function $name(name)
{
	return $('*[name=' + name + ']');
}

function $id(id)
{
	return $('#' + id);
}

window.__folks = new FolksManager();